﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Caching;
using System.Collections;
using System.Threading;
using yq.CacheHelp;

namespace yq.CacheHelp.WebCache
{
    internal class WebClient<T> : yq.CacheHelp.IClient<T> where T : class,new()
    {
        ConfigHost config = new ConfigHost();

        public WebClient(ConfigHost _config)
        {
            config = _config;
        }

        /// <summary>
        /// 内部共享锁
        /// </summary>
        private static readonly ReaderWriterLockSlim locker = new ReaderWriterLockSlim();

        private string _FullName;

        private string FullName
        {
            get
            {
                if (string.IsNullOrEmpty(_FullName))
                {
                    _FullName = config.FullName;
                }
                return _FullName;
            }
        }

        /// <summary>
        /// 将string 转换为对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="str"></param>
        /// <returns></returns>
        private K objectGet<K>(string str)
        {
            return Newtonsoft.Json.JsonConvert.DeserializeObject<K>(str);
        }

        /// <summary>
        /// 将string 转换为对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="str"></param>
        /// <returns></returns>
        private K objectGet<K>(object obj)
        {
            return objectGet<K>(obj.ToString());
        }

        /// <summary>
        /// 将对象转换为string
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        private string objectSet(object m)
        {
            return Newtonsoft.Json.JsonConvert.SerializeObject(m);
        }

        /// <summary>
        /// 根据T返回cache中的Hashtable
        /// </summary>
        /// <returns></returns>
        private Hashtable HashRead
        {
            get
            {
                locker.EnterReadLock();
                try
                {
                    return GetCache[FullName] as Hashtable ?? new Hashtable();
                }
                finally
                {
                    locker.ExitReadLock();
                }
            }
        }


        /// <summary>
        /// 写入缓存对象
        /// </summary>
        /// <returns></returns>
        private void HashWrite(Action<Hashtable> action)
        {
            Hashtable hs = null;
            locker.EnterWriteLock();
            try
            {
                hs = GetCache[FullName] as Hashtable;
                if (hs == null)
                {
                    hs = new Hashtable();
                    GetCache[FullName] = hs;
                }
            }
            finally
            {
                locker.ExitWriteLock();
            }

            action(hs);

        }


        /// <summary>
        /// 获取缓存对象
        /// </summary>
        /// <returns></returns>
        private K ReadCache<K>(string fullName) where K : class ,new()
        {
            object obj = GetCache[fullName];
            if (obj == null)
            {
                return new K();
            }
            else
            {
                return objectGet<K>(obj);
            }
        }

        private System.Web.Caching.Cache GetCache
        {
            get
            {
                if (HttpContext.Current == null)
                {
                    throw new Exception("不是web请求，不能访问WebCaChe");
                }
                return HttpContext.Current.Cache;
            }
        }

        /// <summary>
        /// 判断指定的记录是否已经存在缓存中
        /// </summary>
        /// <param name="key">需要判断的主键,一般为对象ID值</param>
        /// <returns></returns>
        public bool HashContains(string key)
        {
            return HashRead.Contains(key);
        }


        /// <summary>
        /// 根据ID集合获取指定对象集合
        /// </summary>
        /// <param name="keys">需要获取的主键,一般为对象ID值</param>
        /// <returns></returns>
        public IList<T> HGet(IList<string> keys)
        {
            IList<T> list = new List<T>();
            foreach (var key in keys)
            {
                list.Add(HGet(key));
            }

            return list;
        }

        /// <summary>
        /// 根据ID集合获取指定对象集合
        /// </summary>
        /// <param name="key">需要获取的主键,一般为对象ID值</param>
        /// <returns></returns>
        public T HGet(string key)
        {
            if (key == null)
            {
                return new T();
            }

            object obj = HashRead[key];

            if (obj == null)
            {
                return new T();
            }
            else
            {
                return objectGet<T>(obj.ToString());
            }

            // return HashRead<T>(key);
        }

        /// <summary>
        /// 根据ID集合获取指定对象集合
        /// </summary>
        /// <param name="keys">需要获取的主键,一般为对象ID值</param>
        /// <returns></returns>
        public IList<T> HGet(string[] keys)
        {
            return HGet(keys.ToList());
        }

        public Dictionary<string, T> HGetAll()
        {
            Dictionary<string, T> dic = new Dictionary<string, T>();
            Hashtable hs = HashRead;
            foreach (string key in hs.Keys)
            {
                dic.Add(key, objectGet<T>(hs[key]));
            }

            return dic;
        }

        public IList<string> HGetAllKeys()
        {
            IList<string> list = new List<string>();
            Hashtable hs = HashRead;
            foreach (string key in hs.Keys)
            {
                list.Add(key);
            }

            return list;
        }

        public IList<T> HGetAllValues()
        {
            IList<T> list = new List<T>();
            Hashtable hs = HashRead;
            foreach (string key in hs.Keys)
            {
                list.Add(objectGet<T>(hs[key]));
            }

            return list;
        }

        public int HGetCount()
        {
            return HashRead.Keys.Count;
        }

        public void HRemove(IList<string> keys)
        {
            Action<Hashtable> showMethod = (Hashtable hs) =>
             {
                 foreach (string key in keys)
                 {
                     hs.Remove(key);
                 }
             };

            HashWrite(showMethod);
        }

        public bool HRemove(string key)
        {
            Action<Hashtable> Method = (Hashtable hs) =>
            {
                hs.Remove(key);
            };
            HashWrite(Method);

            return true;
        }

        public bool HRemoveAll()
        {
            Action<Hashtable> Method = (Hashtable hs) =>
            {
                hs.Clear();
            };
            HashWrite(Method);

            return true;
        }

        public void HSet(Dictionary<string, string> dics)
        {
            Action<Hashtable> Method = (Hashtable hs) =>
            {
                foreach (string key in dics.Keys)
                {
                    hs[key] = dics[key];
                }
            };
            HashWrite(Method);
        }

        public void HSet(Dictionary<string, T> values)
        {
            Action<Hashtable> Method = (Hashtable hs) =>
            {
                foreach (string key in values.Keys)
                {
                    hs[key] = objectSet(values[key]);
                }
            };
            HashWrite(Method);
        }

        public void HSet(IList<string> keys, IList<T> values)
        {
            int length = keys.Count > values.Count ? keys.Count : values.Count;

            Action<Hashtable> Method = (Hashtable hs) =>
            {
                for (int i = 0; i < length; i++)
                {
                    hs[keys[i]] = objectSet(values[i]);
                }
            };

            HashWrite(Method);
        }

        public bool HSet(string key, T value)
        {
            Action<Hashtable> Method = (Hashtable hs) =>
            {
                hs[key] = objectSet(value);
            };

            HashWrite(Method);

            return true;
        }

        public bool HSetIfNotExists(string key, T value)
        {
            Action<Hashtable> Method = (Hashtable hs) =>
            {
                if (hs.ContainsKey(key) == false)
                {
                    hs[key] = objectSet(value);
                }
            };
            HashWrite(Method);

            return true;
        }

        public Dictionary<string, T> KGet(IList<string> keys)
        {
            Dictionary<string, T> dic = new Dictionary<string, T>();
            foreach (string key in keys)
            {
                dic.Add(key, ReadCache<T>(key));
            }

            return dic;
        }

        public T KGet(string key)
        {
            return ReadCache<T>(key);
        }

        public IList<T> KGetList(IList<string> keys)
        {
            IList<T> list = new List<T>();
            foreach (string key in keys)
            {
                list.Add(ReadCache<T>(key));
            }

            return list;
        }

        public void KRemove(IList<string> keys)
        {
            foreach (string key in keys)
            {
                GetCache.Remove(key);
            }
        }

        public bool KRemove(string key)
        {
            GetCache.Remove(key);

            return true;
        }

        public IList<string> KSearchKeys(string pattern)
        {
            IList<string> list = new List<string>();
            System.Web.Caching.Cache ca = GetCache;
            var enumerator = ca.GetEnumerator();
            while (enumerator.MoveNext())
            {
                if (enumerator.Key.ToString().IndexOf(pattern) != -1)
                {
                    list.Add(enumerator.Key.ToString());
                }
            }

            return list;
        }

        public IList<T> KSearchValues(string pattern)
        {
            IList<T> list = new List<T>();
            System.Web.Caching.Cache ca = GetCache;

            var enumerator = ca.GetEnumerator();

            while (enumerator.MoveNext())
            {
                if (enumerator.Key.ToString().IndexOf(pattern) != -1)
                {
                    list.Add(objectGet<T>(enumerator.Value));
                }
            }

            return list;
        }

        public void KSet(Dictionary<string, T> value)
        {
            foreach (string key in value.Keys)
            {
                GetCache[key] = objectSet(value[key]);
            }
        }

        public bool KSet(string key, T value)
        {
            GetCache[key] = objectSet(value);
            return true;
        }

        public bool KSet(string key, T value, DateTime expiresTime)
        {
            GetCache.Insert(key, objectSet(value), null, expiresTime, System.Web.Caching.Cache.NoSlidingExpiration);
            return true;
        }

        public bool KSet(string key, T value, TimeSpan expiresIn)
        {
            GetCache.Insert(key, objectSet(value), null, System.Web.Caching.Cache.NoAbsoluteExpiration, expiresIn);
            return true;
        }

        public bool HashRefreshDelete(string fullname, string key)
        {
            _FullName = fullname;
            Action<Hashtable> Method = (Hashtable hs) =>
            {
                hs.Remove(key);
            };
            HashWrite(Method);

            return true;
        }


        public void HashRefreshLoad(string fullname, string key, object value)
        {
            _FullName = fullname;
            Action<Hashtable> Method = (Hashtable hs) =>
            {
                hs[key] = objectSet(value);
            };

            HashWrite(Method);
        }

        public bool HashRefreshDelete(string fullname)
        {
            _FullName = fullname;
            Action<Hashtable> Method = (Hashtable hs) =>
            {
                hs.Clear();
            };
            HashWrite(Method);

            return true;
        }




        public bool LAdd(T t)
        {
            throw new NotImplementedException();
        }

        public T LPop()
        {
            throw new NotImplementedException();
        }

        public int LCount()
        {
            throw new NotImplementedException();
        }

        public T LIndex(int i)
        {
            throw new NotImplementedException();
        }

        public bool LTrim(int stop, int end)
        {
            throw new NotImplementedException();
        }

        public IList<T> LALL()
        {
            throw new NotImplementedException();
        }

        public void LRemoveAt(int index)
        {
            throw new NotImplementedException();
        }

        public void LRemoveALL()
        {
            throw new NotImplementedException();
        }


        public T LDequeue()
        {
            throw new NotImplementedException();
        }
    }
}
